/**
  ******************************************************************************
  * @file    sensor.c
  * @brief   This file provides code for the configuration
  *          of all used GPIO pins.
  ******************************************************************************
  * @attention
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "bsp.h"
#include "tskcfg.h"
#include "sensor.h"

//#define SENSOR_UART_RX_MAPTO_RS232N1
//#define SENSOR_UART_TX_MAPTO_RS232N1

Sensor_BufStru sensor_rxbuf_isr;

static void sensor_uart_timeout(void)
{
  LL_TIM_InitTypeDef TIM_InitStruct = {0};
  
  SENSOR_OUTTIMER_EnableClock();

  /* TIM4 interrupt Init */
  NVIC_SetPriority(SENSOR_OUTTIMER_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),SENSOR_OUTTIMER_IRQ_PRIORITY, 0));
  NVIC_EnableIRQ(SENSOR_OUTTIMER_IRQn);

  TIM_InitStruct.Prescaler = 100-1;     /* 1us per cnt */;
  TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
  TIM_InitStruct.Autoreload = 1000-1;   /* 1ms */;
  TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
  LL_TIM_Init(SENSOR_OUTTIMER, &TIM_InitStruct);
  
  LL_TIM_EnableARRPreload(SENSOR_OUTTIMER);
  
  LL_TIM_SetClockSource(SENSOR_OUTTIMER, LL_TIM_CLOCKSOURCE_INTERNAL);
  
  LL_TIM_SetOnePulseMode(SENSOR_OUTTIMER, LL_TIM_ONEPULSEMODE_SINGLE);//LL_TIM_ONEPULSEMODE_REPETITIVE
  
  LL_TIM_SetTriggerOutput(SENSOR_OUTTIMER, LL_TIM_TRGO_RESET);
  
  LL_TIM_DisableMasterSlaveMode(SENSOR_OUTTIMER);
  
  LL_TIM_ClearFlag_UPDATE(SENSOR_OUTTIMER);
  
  LL_TIM_EnableIT_UPDATE(SENSOR_OUTTIMER);
  
  LL_TIM_ClearFlag_UPDATE(SENSOR_OUTTIMER);
  
  LL_TIM_DisableCounter(SENSOR_OUTTIMER);
}

void sensor_uart_init(void)
{
  LL_USART_InitTypeDef USART_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  SENSOR_UART_EnableClock();
  SENSOR_UART_IO_EnableClock();
  
  sensor_uart_timeout();
  
  GPIO_InitStruct.Pin = SENSOR_TX_LL_Pin | SENSOR_RX_LL_Pin;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = SENSOR_GPIO_LL_AF;
  LL_GPIO_Init(SENSOR_GPIO_Port, &GPIO_InitStruct);

  /* tx dma init */
  LL_DMA_SetChannelSelection(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, SENSOR_UART_txDMA_CHANNEL);
  LL_DMA_SetDataTransferDirection(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
  LL_DMA_SetStreamPriorityLevel(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_PRIORITY_VERYHIGH);
  LL_DMA_SetMode(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_MODE_NORMAL);
  LL_DMA_SetPeriphIncMode(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_PERIPH_NOINCREMENT);
  LL_DMA_SetMemoryIncMode(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_MEMORY_INCREMENT);
  LL_DMA_SetPeriphSize(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_PDATAALIGN_BYTE);
  LL_DMA_SetMemorySize(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_MDATAALIGN_BYTE);
  LL_DMA_DisableFifoMode(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  LL_DMA_SetFIFOThreshold(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_FIFOTHRESHOLD_FULL);
  LL_DMA_SetMemoryBurstxfer(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_MBURST_SINGLE);
  LL_DMA_SetPeriphBurstxfer(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_DMA_PBURST_SINGLE);
  LL_DMA_DisableDoubleBufferMode(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  LL_DMA_SetPeriphAddress(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, LL_USART_DMA_GetRegAddr(SENSOR_UART));
  
  LL_DMA_DisableIT_HT(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  LL_DMA_DisableIT_DME(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  LL_DMA_DisableIT_FE(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  
  LL_DMA_EnableIT_TC(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  LL_DMA_EnableIT_TE(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
  
  NVIC_SetPriority(SENSOR_UART_txDMA_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),SENSOR_UART_txDMA_IRQ_PRIORITY, 0));
  NVIC_EnableIRQ(SENSOR_UART_txDMA_IRQn);

  NVIC_SetPriority(SENSOR_UART_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),SENSOR_UART_IRQ_PRIORITY, 0));
  NVIC_EnableIRQ(SENSOR_UART_IRQn);
  
  USART_InitStruct.BaudRate = SENSOR_UART_BAUDRATE;
  USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
  USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
  USART_InitStruct.Parity = LL_USART_PARITY_NONE;
  USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
  USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
  LL_USART_Init(SENSOR_UART, &USART_InitStruct);
  
  LL_USART_SetOverSampling(SENSOR_UART, LL_USART_OVERSAMPLING_16);
  
  LL_USART_DisableOneBitSamp(SENSOR_UART);
  
  LL_USART_ConfigAsyncMode(SENSOR_UART);
  
  LL_USART_DisableIrda(SENSOR_UART);
  
  LL_USART_DisableSmartcard(SENSOR_UART);
  
  LL_USART_DisableHalfDuplex(SENSOR_UART);
  
  LL_USART_DisableLIN(SENSOR_UART);
  
  LL_USART_SetWakeUpMethod(SENSOR_UART, LL_USART_WAKEUP_IDLELINE);

  LL_USART_Enable(SENSOR_UART);
  
  LL_USART_EnableIT_RXNE(SENSOR_UART);
  LL_USART_EnableIT_ERROR(SENSOR_UART);
}

void sensor_send_str(const char *buf)
{
  uint32_t i;
  
  for(i=0; buf[i]!='\0'; i++)
  {
    SENSOR_UART->DR = (buf[i] & (uint16_t)0x01FFU);
    while(READ_BIT(SENSOR_UART->SR, USART_SR_TXE) != (USART_SR_TXE));
  }
  
  while(READ_BIT(SENSOR_UART->SR, USART_SR_TC) != (USART_SR_TC));
}

void sensor_send_buf(const uint8_t *buf, uint32_t len)
{
  uint32_t i;
  
  for(i=0; i<len; i++)
  {
    SENSOR_UART->DR = (buf[i]& (uint16_t)0x01FFU);
    while(READ_BIT(SENSOR_UART->SR, USART_SR_TXE) != (USART_SR_TXE));
  }
  
  while(READ_BIT(SENSOR_UART->SR, USART_SR_TC) != (USART_SR_TC));
}

/* 仅在相应的唯一任务下被调用 */
void sensor_dma_send_buf(const uint8_t *buf, uint16_t len)
{
  uint32_t ulNotifiedValue;  /* 这个值不用初始化 通知函数中会有处理 */
  
  WRITE_REG(SENSOR_UART_txDMA->HIFCR, DMA_HIFCR_CTCIF4|DMA_HIFCR_CHTIF4|DMA_HIFCR_CTEIF4|DMA_HIFCR_CDMEIF4|DMA_HIFCR_CFEIF4);
  LL_USART_ClearFlag_TC(SENSOR_UART);
  
  LL_DMA_SetMemoryAddress(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, (uint32_t)buf);
  LL_DMA_SetDataLength(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM, len);
  
/* 启动传输 */
  xTaskNotifyStateClear(xSensor_Thd);
  
  LL_USART_EnableDMAReq_TX(SENSOR_UART);
  LL_DMA_EnableStream(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);

/* 等待完成 */
  if(xTaskNotifyWait(0xffffffffu, 0xffffffffu, &ulNotifiedValue, 100) == pdTRUE)
  {
    /* 这里不做任何处理,成功不成功反正一直要发 */
  }  
  
  while(READ_BIT(SENSOR_UART->SR, USART_SR_TC) != (USART_SR_TC));
  
/* 传输完成 */
  LL_USART_DisableDMAReq_TX(SENSOR_UART);
  LL_DMA_DisableStream(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM);
}

void SENSOR_UART_IRQHandler(void)
{
  if(READ_BIT(SENSOR_UART->SR, USART_SR_RXNE) == (USART_SR_RXNE))
  {
    CLEAR_BIT(SENSOR_OUTTIMER->CR1, TIM_CR1_CEN);
    
    if(sensor_rxbuf_isr.cnt <= SENSOR_FRAME_BUFLEN){
      sensor_rxbuf_isr.buf[sensor_rxbuf_isr.cnt++] = (uint8_t)(READ_BIT(SENSOR_UART->DR, USART_DR_DR));
    }else{
      sensor_rxbuf_isr.cnt = 0;
    }

#ifdef SENSOR_UART_RX_MAPTO_RS232N1
    UART5->DR = (uint8_t)(READ_BIT(SENSOR_UART->DR, USART_DR_DR));
#endif

    WRITE_REG(SENSOR_OUTTIMER->CNT, 0);
    SET_BIT(SENSOR_OUTTIMER->CR1, TIM_CR1_CEN);
  }
}

void SENSOR_UART_txDMA_IRQHandler(void)
{
  if((LL_DMA_IsActiveFlag_TC4(SENSOR_UART_txDMA) != 0) && (LL_DMA_IsEnabledIT_TC(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM) != 0))
  {
    LL_DMA_ClearFlag_TC4(SENSOR_UART_txDMA);
    
    xTaskNotifyFromISR(xSensor_Thd, 0x01u, eSetBits, NULL);
  }
  
 if((LL_DMA_IsActiveFlag_HT4(SENSOR_UART_txDMA) != 0) && (LL_DMA_IsEnabledIT_HT(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM) != 0))
 {
   LL_DMA_ClearFlag_HT4(SENSOR_UART_txDMA);
   xTaskNotifyFromISR(xSensor_Thd, 0x02u, eSetBits, NULL);
 }
  
  if((LL_DMA_IsActiveFlag_TE4(SENSOR_UART_txDMA) != 0) && (LL_DMA_IsEnabledIT_TE(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM) != 0))
  {
    LL_DMA_ClearFlag_TE4(SENSOR_UART_txDMA);
    xTaskNotifyFromISR(xSensor_Thd, 0x04u, eSetBits, NULL);
  }
  
  if((LL_DMA_IsActiveFlag_FE4(SENSOR_UART_txDMA) != 0) && (LL_DMA_IsEnabledIT_FE(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM) != 0))
  {
    LL_DMA_ClearFlag_FE4(SENSOR_UART_txDMA);
    xTaskNotifyFromISR(xSensor_Thd, 0x08u, eSetBits, NULL);
  }
  
  if((LL_DMA_IsActiveFlag_DME4(SENSOR_UART_txDMA) != 0) && (LL_DMA_IsEnabledIT_DME(SENSOR_UART_txDMA, SENSOR_UART_txDMA_STREAM) != 0))
  {
    LL_DMA_ClearFlag_DME4(SENSOR_UART_txDMA);
    xTaskNotifyFromISR(xSensor_Thd, 0x10u, eSetBits, NULL);
  }
}

void SENSOR_OUTTIMER_IRQHandler(void)
{
  if(LL_TIM_IsActiveFlag_UPDATE(SENSOR_OUTTIMER) == 1)
  {
    LL_TIM_ClearFlag_UPDATE(SENSOR_OUTTIMER);
    
    if(sensor_rxbuf_isr.cnt > 5)
    {
      xQueueSendFromISR(sensor_recv_qhd, &sensor_rxbuf_isr, NULL);
    }
    
    sensor_rxbuf_isr.cnt = 0;
  }
}
